package com.heima.comment.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.heima.aliyun.scan.GreenScan;
import com.heima.aliyun.scan.ScanResult;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.exception.CustException;
import com.heima.feigns.ArticleFeign;
import com.heima.feigns.UserFeign;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.comment.dtos.CommentDTO;
import com.heima.model.comment.dtos.CommentLikeDTO;
import com.heima.model.comment.dtos.CommentSaveDTO;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CommentServiceImpl implements CommentService {
    @Autowired
    private GreenScan greenScan;

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private ArticleFeign articleFeign;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    RedissonClient redisson;

//    @Autowired
//    private CommentHotService commentHotService;

    /**
     * 保存评论
     *
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDTO dto) {
        //1. 校验参数
        if (dto == null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //   校验是否登录
        ApUser apUser = AppThreadLocalUtils.getUser();
        if (apUser == null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2.阿里云校验评论内容是否违规
//阿里云校验评论内容是否违规
        try {
            ScanResult scanResult = greenScan.greenTextScan(dto.getContent());
            String suggestion = scanResult.getSuggestion();
            switch (suggestion) {
                case "block":
                    log.error("评论信息含有违规内容 ===>原因：{}" + scanResult.getReason());
                    CustException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW, scanResult.getReason());
                    break;
                case "review":
                    dto.setContent(scanResult.getFilteredContent());
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云文本审核出现异常 , 原因:{}", e.getMessage());
        }
        //远程查询当前登陆用户信息
        ResponseResult<ApUser> userReault = userFeign.findUserById(apUser.getId());
        if (!userReault.checkCode()) {
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR);
        }
        ApUser user = userReault.getData();
        //3. 远程查询当前登陆用户信息
        ResponseResult<ApArticle> apArticleResult = articleFeign.findArticleById(dto.getArticleId());
        ApArticle apArticle = apArticleResult.getData();
        //创建评论信息，并保存到mongo
        ApComment apComment = new ApComment();
        apComment.setAuthorId(user.getId());
        apComment.setAuthorName(user.getName());
        apComment.setArticleId(dto.getArticleId());
        apComment.setType((short) 0);
        apComment.setChannelId(apArticle.getChannelId());
        apComment.setContent(dto.getContent());
        apComment.setImage(user.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setFlag((short) 0);
        apComment.setLongitude(new BigDecimal("0"));
        apComment.setLatitude(new BigDecimal("0"));
        apComment.setAddress("");
        apComment.setOrd(0);
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        //保存
        mongoTemplate.save(apComment);
        return ResponseResult.okResult(apComment);
    }
    @Autowired
    CommentHotService commentHotService;
    /**
     * 点赞评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDTO dto) {
        Map<String, Integer> map = new HashMap<>();
        //判断用户是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        //查询ApComment的实体类
        Query Likequery = Query.query(Criteria.where("id").is(dto.getCommentId()));
        ApComment apComment = mongoTemplate.findOne(Likequery, ApComment.class);
        if (apComment == null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        RLock lock = redisson.getLock("likes-lock");
        lock.lock();
        try {
            //查询点赞的实体类
            Query query = Query.query(Criteria.where("commentId").is(apComment.getId()).and("authorId").is(user.getId()));
            ApCommentLike apCommentLike = mongoTemplate.findOne(query, ApCommentLike.class);
            if (apCommentLike == null) {
                CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST);
            }
            //判断是否是点赞操作
            if (dto.getOperation().intValue() == 0) {
                if (apCommentLike.getOperation().intValue() == 0) {
                    CustException.cust(AppHttpCodeEnum.DATA_EXIST, "请勿重复点赞");
                } else {
                    //没有点过赞  创建点赞对象
                    apCommentLike = new ApCommentLike();
                    apCommentLike.setAuthorId(user.getId());
                    apCommentLike.setCommentId(dto.getCommentId());
                    apCommentLike.setOperation(dto.getOperation());
                    //插入数据库
                    mongoTemplate.save(apCommentLike);
                    apComment = new ApComment();
                    apComment.setLikes(apComment.getLikes() + 1);
                    mongoTemplate.save(apComment);
                    map.put("likes", apComment.getLikes());
                    //计算热点评论评论
                    if (apComment.getLikes() >= 10 && apComment.getFlag() == 0) {
                        commentHotService.hotCommentExecutor(apComment);
                    }
                }
            } else {
                mongoTemplate.remove(apCommentLike);
                apComment = new ApComment();
                apComment.setLikes(apComment.getLikes() - 1);
                mongoTemplate.save(apComment);
                map.put("likes", apComment.getLikes());
            }
        } finally {
            lock.lock();
        }

        return ResponseResult.okResult(map);
    }

    /**
     * 根据文章id查询评论列表
     *
     * @return
     */
    @Override
    public ResponseResult findByArticleId(CommentDTO dto) {
        //参数校验
        if (dto.getMinDate() == null) {
            dto.setMinDate(new Date());
        }
        Integer size = dto.getSize();
        if (size == null || size == 0) {
            dto.setSize(10);
        }
        // 判断是否
        //2 查询Mongo文章所有评论列表
        List<ApComment> apCommentList;
        // 文章评论的首页
        if (dto.getIndex().intValue() == 1) {
            //查询热点评论  5
            Query query = Query.query(Criteria.where("articleId").is(dto.getArticleId()).and("flag").is(1)).with(Sort.by(Sort.Direction.DESC, "likes"));
            apCommentList = mongoTemplate.find(query, ApComment.class);
            // 热点集合不为空
            if (CollectionUtils.isNotEmpty(apCommentList)) {
                size = size - apCommentList.size();
                List<ApComment> normalComments = mongoTemplate.find(getQuery(dto, size), ApComment.class);
                apCommentList.addAll(normalComments);
            } else {
                apCommentList = mongoTemplate.find(
                        getQuery(dto, size),
                        ApComment.class
                );
            }
        } else {
            apCommentList = mongoTemplate.find(
                    getQuery(dto, size),
                    ApComment.class
            );
        }
        //3 封装查询结果
        //3.1 用户未登录 直接返回评论列表
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            return ResponseResult.okResult(apCommentList);
        }
        //3.2 用户登录，需要加载当前用户对评论点赞的列表
        // 获取文章对应的所有评论ID列表
        List<String> idList = apCommentList.stream()
                .map(ApComment::getId)
                .collect(Collectors.toList());
        // 查询 点赞批量列表 按照评论id 筛选
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(
                Query.query(Criteria.where("commentId").in(idList)
                        .and("authorId").is(user.getId()))
                , ApCommentLike.class);
        // 遍历当前用户点赞列表 和当前评论列表
        if (CollectionUtils.isNotEmpty(apCommentList)
                && CollectionUtils.isNotEmpty(apCommentLikes)) {
            // 获取点过赞的评论id
            List<String> commentIds = apCommentLikes.stream()
                    .map(ApCommentLike::getCommentId).collect(Collectors.toList());
            // 遍历评论列表，将comment 转为 commentVO
            return ResponseResult.okResult(apCommentList.stream()
                    .map(comment -> parseCommentVO(comment, commentIds)));
        }
        return ResponseResult.okResult(apCommentList);
        //        Query query = Query.query(Criteria.where("articleId").is(dto.getArticleId()).and("flag").is((short) 0));
//        query.limit(dto.getSize());//分页
//
//        Sort sort = Sort.by(Sort.Direction.DESC, "createdTime");
//        query.with(sort);// 排序
//        List<ApComment> apComments = mongoTemplate.find(query, ApComment.class);
//        //判断用户是否登录
//        ApUser user = AppThreadLocalUtils.getUser();
//        if (user == null) {
//            //返回品评论列表
//            return ResponseResult.okResult(apComments);
//        }
//        //需要检查在当前评论列表中 哪些评论登录人点赞过
//        Query query1 = Query.query(Criteria.where("authorId").is(user.getId())
//                .and("operation").is((short) 0));
//        List<ApCommentLike> apCommentLikes = mongoTemplate.find(query1, ApCommentLike.class);
//        //获取当前登录用户的点赞评论id集合
//        List<String> likeIds = new ArrayList<>();
//        for (ApCommentLike apCommentLike : apCommentLikes) {
//            likeIds.add(apCommentLike.getCommentId());
//        }
//        ArrayList<ApCommentVo> commentVos = new ArrayList<>();
//        for (ApComment apComment : apComments) {
//            ApCommentVo apCommentVo = new ApCommentVo();
//            BeanUtils.copyProperties(apComment, apCommentVo);
//            commentVos.add(apCommentVo);
//        }
//        //如果当前评论id在点赞记录中存在  设置operation字段为0
//        for (ApCommentVo commentVo : commentVos) {
//            if (likeIds.contains(commentVo.getId())) {
//                commentVo.setOperation((short) 0);
//            }
//        }
//        return ResponseResult.okResult(commentVos);
    }

    /**
     * 将comment 转为 vo对象   根据likes情况判断是否点过赞
     *
     * @param apComment
     * @param commentIds
     * @return
     */
    private ApCommentVo parseCommentVO(ApComment apComment, List<String> commentIds) {
        ApCommentVo apCommentVo = new ApCommentVo();
        BeanUtils.copyProperties(apComment, apCommentVo);
        //遍历当前用户点赞列表
        if (commentIds.contains(apCommentVo.getId())) {
            apCommentVo.setOperation((short) 0);
        }
        return apCommentVo;
    }

    /**
     * 构建查询条件
     */
    private Query getQuery(CommentDTO dto, Integer size) {
        return Query.query(Criteria.where("articleId").is(dto.getArticleId())
                .and("flag").is(0).and("createdTime").lt(dto.getMinDate()))
                .limit(size).with(Sort.by(Sort.Direction.DESC, "createdTime"));
    }
}
